package cn.ycc1.boot3thread.service.impl;

import cn.ycc1.boot3thread.config.CompletableTask;
import cn.ycc1.boot3thread.service.ThreadRedissonService;
import cn.ycc1.boot3thread.user.domain.User;
import cn.ycc1.boot3thread.user.service.UserService;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

/**
 * @author ycc
 * @date 2024/7/28
 */
@Service
@RequiredArgsConstructor
public class ThreadRedissonServiceImpl implements ThreadRedissonService {
    private final Executor myCompletableTaskExecutor;
    private final UserService userService;
    private final RedissonClient redissonClient;

    @Override
    public void test() {
        CompletableTask.allOf(
                myCompletableTaskExecutor,
                () -> {
                    thread1();
                },
                () -> {
                    thread2();
                }
        );
    }

    private void thread2() {
        CompletableTask.allOf(
                myCompletableTaskExecutor,
                () -> {
                    this.updateUser(2L, 1L);
                },
                () -> {
                    this.updateUser(2L, 2L);
                }
        );
        System.out.println("------------thread2");
    }

    private void thread1() {
        CompletableTask.allOf(
                myCompletableTaskExecutor,
                () -> {
                    this.updateUser(2L, 3L);
                },
                () -> {
                    this.updateUser(2L, 4L);
                }
        );
        System.out.println("------------thread1");
    }

    /**
     * 更新用户的字段值
     *
     * @param uid
     * @param amount
     * @return
     */
    @Transactional
    protected Boolean updateUser(Long uid, Long amount) {
        RLock lock = redissonClient.getLock("myLock");
        try {
            // 尝试获取锁，等待最多10秒，锁定时间为60秒
            if (lock.tryLock(10, 60, TimeUnit.SECONDS)) {
                try {
                    // 在这里执行你的业务逻辑
                    User user = userService.getById(uid);
                    user.setDeptId(user.getDeptId() + amount);
                    return userService.updateById(user);
                } finally {
                    lock.unlock();
                }
            } else {
                // 无法获取锁，处理失败情况
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return false;
    }
}
